package com.test.springboot.springBootUtils.advice;

import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.test.springboot.springBootUtils.bean.ResultVo;
import com.test.springboot.springBootUtils.exception.APIException;

/**
 * 对全局所有的Controller中返回 Response 进行处理
 * 对Controller中的方法进行增强  
 * 
 * @author huyong
 *
 */
@RestControllerAdvice(basePackages = { "com.test.springboot.springBootUtils.controller" }) // 需要扫描的controller的包
public class ResponseControllerAdvice implements ResponseBodyAdvice<Object> {
	/**
	 * 判断当前方法是否需要被增强  返回 true 才被增强  返回 false 不需要被增强
	 */
	@Override
	public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
		// 这里判断接口是否返回的是 ResultVo 如果是就是已经处理过的，这里没必要再次判断
		return !returnType.getParameterType().equals(ResultVo.class);
	}

	/**
	 * 真正被增强的方法  只有当 supports 方法 返回true了  才会走当前方法
	 * 可以在这个方法中直接包装需要返回的数据，无需每个接口都进行包装
	 */
	@Override
	public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
		// 如果接口返回的是String类型 这里无法直接进行转换 ，先将String转换成 JSON 对象才行
		if (returnType.getGenericParameterType().equals(String.class)) {
			ObjectMapper mapper = new ObjectMapper();
			try {
				// 将数据包装在ResultVo 里面，在转换为JSON字符串响应给前端
				return mapper.writeValueAsString(new ResultVo<>(body));
			} catch (Exception e) {
				throw new APIException("返回String类型错误");
			}
		}
		return new ResultVo<>(body);
	}

}
